home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
linklist
/
source.lha
/
list.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-08
|
41KB
|
1,849 lines
/*
** Anita Eijs TNO-BOUW, BouwInformatica May 1989
**
** Generic Linked List Package
**
** Updates:
** 900402 New routine:
** lIndxNode Get node by index.
**
** 900925 New routine:
** lError print error message in lERROR_FILE
**
** 901129 New routines:
** lDump Dump a linked list to a file.
** lUndump Undump a linked list from a file.
**
** 910301 'Mac'ed by Vinnie:
** ListPtr = ListyPtr
** Byte = byte
** includes
** typecasts
**
** 910316 New routine:
** lFlagNode Get node by flag.
**
** ***** Version 0.7, March 1992 *****
**
** 930401 Several updates by Anita and Shane.
** Some functions renamed:
** lIndxNode --> lGetIndxNode
** lFlagNode --> lFndFlagNode
** New routines:
** lSort Sort a linked list.
** lInfoIndxNode Get information about node by index.
** lDelIndxNode Delete node by index.
** lUpdIndxNode Update node by index.
** Parameter where added to lFndFlagNode to find several nodes
** matching the requested flag.
** Defines are made more specific; FIRST is renamed in lFIRST, etc.
**
** ***** Version 0.8, May 1993 *****
*/
#ifdef MAC
#define MAC_OR_VAXC
#endif
#ifdef VAXC
#define MAC_OR_VAXC
#define MSDOS_OR_VAXC
#endif
#ifdef MSDOS
#define MSDOS_OR_VAXC
#endif
#ifdef MAC
#include <unix.h> /* open, creat, write, read, close */
#include <stddef.h> /* sizeof */
#endif
#ifdef MAC_OR_VAXC
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#ifdef MSDOS
#include <io.h> /* open, creat, write, read, close */
#endif
#include <stdio.h>
#include "list.h"
/* -------------------------------------------------------------------------- */
#ifndef NULL
#define NULL 0
#endif
#undef FREE
#define FREE(VAR) if (VAR != NULL) free((char *)VAR);
#undef MALLOC
#define MALLOC(VAR, TYPE) \
if ((VAR = (TYPE *)malloc(sizeof(TYPE))) == NULL) { \
fprintf(stderr, "No more memory for malloc().\n"); \
}
#undef CALLOC
#define CALLOC(VAR, TYPE, NR) \
if ((VAR = (TYPE *)calloc(NR, sizeof(TYPE))) == NULL) {\
fprintf(stderr, "No more memory for calloc().\n"); \
}
#undef BYTE_COPY
#define BYTE_COPY(FROM, TO, SIZE) \
{ \
register Byte *frm = FROM, \
*to = TO; \
int i = SIZE; \
while (i--) *to++ = *frm++; \
}
#define BIN_WRITE 1 /* necessary for binary file access */
#define BIN_READ 0
#define PMODE 0666
/* -------------------------------------------------------------------------- */
#ifndef ANSI
typedef int (*Func)();
typedef unsigned char Byte;
#endif
typedef struct lnode {
Byte *data; /* data of user */
int size; /* size (number of bytes) of data */
int flag; /* user information flag */
struct lnode *prv; /* previous node */
struct lnode *nxt; /* next node */
} ListNode, *NodePtr;
typedef struct listhdr {
int id; /* identifier of linked list */
int sd; /* singly or doubly linked */
int cc; /* chain or circular list */
int n; /* number of nodes */
NodePtr first; /* address of first node */
NodePtr current; /* address of current node */
NodePtr last; /* address of last node */
struct listhdr *nxt; /* next linked list */
} ListHdr, *ListPtr;
typedef struct header { /* general info of linked list for dump file */
int sd;
int cc;
int n;
} Header;
typedef struct info { /* general info of node for dump file */
int size;
int flag;
} Info;
/* -------------------------------------------------------------------------- */
#ifdef ANSI
static ListPtr getAddress(int id);
static void delNodes(NodePtr node, int n);
static void delListInfo(ListPtr list);
static void lError(char *str, int code, int int1, int int2, char *str1);
static int setWhchNode(int id, int which, char *fname);
static int setIndxNode(int id, int index, char *fname);
static int partition(NodePtr *array, int order, Func func, int lb, int ub,
int *pj);
static int stack_empty(int id);
static int intInSet(int intgr, int *set, int set_n);
#else
static ListPtr getAddress();
static void delNodes();
static void delListInfo();
static void lError();
static int setWhchNode();
static int setIndxNode();
static int partition();
static int stack_empty();
static int intInSet();
#endif
/* -------------------------------------------------------------------------- */
static ListHdr firstlist = { 1, 0, 0, 0, NULL, NULL, NULL, NULL };
static ListPtr ld = &firstlist;
static int idMax = 2;
/* -------------------------------------------------------------------------- */
/*******************************************************************************
** Define a new linked list and create info about it.
**
** Parameters:
** In int sd singly or doubly linked
** (lSINGLY, lDOUBLY)
** In int cc chain or circular linked
** (lCHAIN, lCIRCULAR)
**
** Return on success:
** identifier of linked list
** Return on error:
** lWRONG_SD, lWRONG_CC
*/
#ifdef ANSI
int
lDef(int sd, int cc)
#else
int
lDef(sd, cc)
int sd, cc;
#endif
{
ListPtr list, new;
static int set1[] = { lSINGLY, lDOUBLY },
set2[] = { lCHAIN, lCIRCULAR };
/* check parameters */
if (intInSet(sd, set1, 2) != 0) {
lError("lDef", lWRONG_SD, sd, 0, NULL);
return(lWRONG_SD);
}
if (intInSet(cc, set2, 2) != 0) {
lError("lDef", lWRONG_CC, cc, 0, NULL);
return(lWRONG_CC);
}
list = ld;
while (list->nxt != NULL && list->sd != 0)
list = list->nxt;
if (list->sd != 0) { /* new list */
MALLOC(new, ListHdr);
new->id = idMax++;
new->sd = sd;
new->cc = cc;
new->n = 0;
new->first = new->current = new->last = NULL;
new->nxt = NULL;
list->nxt = new;
return(new->id);
} else { /* new list on existing place */
list->sd = sd;
list->cc = cc;
return(list->id);
}
}
/*******************************************************************************
** Get info of linked list.
**
** Parameters:
** In int id identifier of linked list
** Out int *sd singly or doubly linked
** (lSINGLY, lDOUBLY)
** Out int *cc chain or cicular linked
** (lCHAIN, lCIRCULAR)
** Out int *n number of nodes
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID
*/
#ifdef ANSI
int
lInfo(int id, int *sd, int *cc, int *n)
#else
int
lInfo(id, sd, cc, n)
int id, *sd, *cc, *n;
#endif
{
ListPtr list;
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lInfo", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
/* copy information */
*sd = list->sd;
*cc = list->cc;
*n = list->n;
return(lSUCCESS);
}
/*******************************************************************************
** Sort a linked list.
**
** Parameters:
** In int id identifier of linked list
** In int order sorting order
** (lDESCENDING, lASCENDING)
** In int theory sorting theory
** (lBUBBLE, lHEAP, lINSERT, lQUICK, lSELECTION)
** In Func func number of nodes
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_ORDER, lWRONG_THEORY
*/
#ifdef ANSI
int lSort(int id, int order, int theory, Func func)
#else
int
lSort(id, order, theory, func)
int id, order, theory;
Func func;
#endif
{
int node_n, i, s, f, k, where, j, cmp;
ListPtr list;
NodePtr temp, temp2, *array;
static int set1[] = { lASCENDING, lDESCENDING },
set2[] = { lBUBBLE, lHEAP, lINSERT, lQUICK,
lSELECTION };
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lSort", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError("lSort", lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
if (intInSet(order, set1, 2) != 0) {
lError("lSort", lWRONG_ORDER, id, 0, NULL);
return(lWRONG_ORDER);
}
if (intInSet(theory, set2, 5) != 0) {
lError("lSort", lWRONG_THEORY, id, 0, NULL);
return(lWRONG_THEORY);
}
node_n = list->n;
/* allocate 1 extra so I can nave a null in it */
CALLOC(array, NodePtr, node_n+1);
list->current = list->first;
for (i=0; i<node_n && list->current != NULL ; i++) {
array[i] = list->current;
list->current = (list->current)->nxt;
}
array[node_n] = NULL;
switch (theory) {
case lBUBBLE: {
int switched = 1;
for (i=0; i < node_n-1 && switched == 1; i++) {
switched = 0;
for (j=0; j < node_n-i-1; j++) {
cmp = (*func)(array[j]->data, array[j+1]->data);
if ((order == lASCENDING && cmp == l2LT1)
|| (order == lDESCENDING && cmp == l1LT2)) {
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
switched = 1;
}
}
}
break;
} /* end of lBUBBLE */
case lHEAP:
for (i=1; i<node_n; i++) {
temp = array[i];
s = i;
f = (s-1)/2;
cmp = (*func)(array[f]->data, temp->data);
while (s > 0 && ((order == lASCENDING && cmp == l1LT2)
|| (order == lDESCENDING && cmp == l2LT1))) {
array[s] = array[f];
s = f;
f = (s-1)/2;
cmp = (*func)(array[f]->data, temp->data);
}
array[s] = temp;
}
for (i=node_n-1; i>0; i--) {
temp = array[i];
array[i] = array[0];
f = 0;
if (i == 1)
s = -1;
else
s = 1;
cmp = (*func)(array[2]->data, array[1]->data);
if (i > 2 && ((order == lASCENDING && cmp == l2LT1)
|| (order == lDESCENDING && cmp == l1LT2)))
s = 2;
if (s >= 0)
cmp = (*func)(temp->data, array[s]->data);
while (s >= 0 && ((order == lASCENDING && cmp == l1LT2)
|| (order == lDESCENDING && cmp == l2LT1))) {
array[f] = array[s];
f = s;
s = 2*f+1;
if (s+1 <= i-1) {
cmp = (*func)(array[s]->data,
array[s+1]->data);
if (cmp < 0)
s = s+1;
}
if (s > i-1)
s = -1;
if (s >= 0)
cmp = (*func)(temp->data,
array[s]->data);
}
array[f] = temp;
}
break;
case lINSERT:
for (i=1; i<node_n; i++) {
temp = array[i];
cmp = (*func)(temp->data, array[i-1]->data);
for (j=i-1; j>=0
&& ((order == lASCENDING && cmp == l1LT2)
|| (order == lDESCENDING && cmp == l2LT1)); j--) {
temp2 = array[j];
array[j] = array[j+1];
array[j+1] = temp2;
if (j > 0)
cmp = (*func)(temp->data,
array[j-1]->data);
}
}
break;
case lQUICK: {
struct bndtype {
int lb;
int ub;
} newbnds;
int newbndsSz = sizeof(struct bndtype),
stack = lDef(lDOUBLY, lCHAIN);
newbnds.lb = 0;
newbnds.ub = node_n-1;
/* basicly a push */
lInsNode(stack, lLAST, &newbnds, newbndsSz, 0);
/* repeat as long as there are any unsorted subarrays
** on the stack */
while (!stack_empty(stack)) {
/* a pop */
lGetNode(stack, lCURRENT, &newbnds, newbndsSz);
lDelNode(stack, lCURRENT);
while (newbnds.ub > newbnds.lb) {
/* process next sub array */
partition(array, order, (*func), newbnds.lb,
newbnds.ub, &j);
/* stack the larger subarray */
if (j-newbnds.lb > newbnds.ub-j) {
/* stack lower subarray */
i = newbnds.ub;
newbnds.ub = j-1;
/* basicly a push */
lInsNode(stack, lLAST, &newbnds,
newbndsSz, 0);
/* process upper subarray */
newbnds.lb = j+1;
newbnds.ub = i;
} else {
/* stack upper subarray */
i = newbnds.lb;
newbnds.lb = j+1;
/* basicly a push */
lInsNode(stack, lLAST, &newbnds,
newbndsSz, 0);
/* process lower subarray */
newbnds.lb = i;
newbnds.ub = j-1;
}
}
}
lDel(stack);
break;
} /* end of lQUICK */
case lSELECTION: {
int indx;
for (i=node_n-1; i>0 ; i--) {
temp = array[0];
indx = 0;
for (j=1; j<=i; j++) {
cmp = (*func)(array[j]->data, temp->data);
if ((order == lASCENDING && cmp == l2LT1)
|| (order == lDESCENDING && cmp == l1LT2)) {
temp = array[j];
indx = j;
}
}
array[indx] = array[i];
array[i] = temp;
}
break;
} /* end of lSELECTION */
} /* end of switch */
/* init list to start and reset it */
list->first = array[0];
list->last = array[node_n-1];
list->current = list->first;
for (k=0; k<node_n; k++) {
if (k == 0)
where = lFIRST;
else if (k == node_n)
where = lLAST;
else
where = lNEXT;
switch (where) {
case lFIRST:
if (list->cc == lCIRCULAR)
(list->first)->prv = (list->last);
if (list->sd == lDOUBLY)
array[k]->prv = NULL;
array[k]->nxt = array[k+1];
break;
case lNEXT:
if (list->sd == lDOUBLY)
(list->first)->prv = array[k-1];
array[k]->nxt = array[k+1];
break;
case lLAST:
if (list->sd == lDOUBLY)
array[k]->prv = array[k-1];
if (list->cc == lCIRCULAR)
array[k]->nxt = list->first;
else
array[k]->nxt = NULL;
break;
}
}
FREE(array);
return(lSUCCESS);
}
/*******************************************************************************
** Dump a linked list to a file.
**
** Parameters:
** In int id identifier of linked list
** In char *file name of linked list dump file
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lOPEN_ERROR
**
** File structure:
** <header> { <info> <data> }
** header.n number of <info>-<data>-combinations (nodes)
** info.size size of <data>
*/
#ifdef ANSI
int
lDump(int id, char *file)
#else
int
lDump(id, file)
int id;
char *file;
#endif
{
#ifndef MSDOS
int open(), creat(), write(), close();
#endif
int fdDump, i;
ListPtr list;
NodePtr node;
Info info;
Header header;
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lDump", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
fdDump = open(file, BIN_WRITE);
if (fdDump == -1) {
fdDump = creat(file, PMODE);
if (fdDump == -1) {
lError("lDump", lOPEN_ERROR, 0, 0, file);
return(lOPEN_ERROR);
}
}
header.sd = list->sd;
header.cc = list->cc;
header.n = list->n;
write(fdDump, (char *) &header, sizeof(Header));
node = list->first;
for (i=0; i<header.n; i++) {
info.size = node->size;
info.flag = node->flag;
write(fdDump, (char *) &info, sizeof(Info));
write(fdDump, (char *) node->data, node->size);
node = node->nxt;
}
close(fdDump);
return(lSUCCESS);
}
/*******************************************************************************
** Undump a linked list from a file.
**
** Parameters:
** In char *file name of linked list dump file
**
** Return on success:
** lSUCCESS
** Return on error:
** lOPEN_ERROR
*/
#ifdef ANSI
int
lUndump(char *file)
#else
int
lUndump(file)
char *file;
#endif
{
#ifndef MSDOS
int open(), read(), close();
#endif
int fdDump, i, id;
Info info;
Header header;
Byte *data;
/* check parameters */
fdDump = open(file, BIN_READ);
if (fdDump == -1) {
lError("lDump", lOPEN_ERROR, 0, 0, file);
return(lOPEN_ERROR);
}
read(fdDump, (char *) &header, sizeof(Header));
id = lDef(header.sd, header.cc);
for (i=0; i<header.n; i++) {
read(fdDump, (char *) &info, sizeof(Info));
CALLOC(data, Byte, info.size);
read(fdDump, (char *) data, info.size);
lInsNode(id, lLAST, data, info.size, info.flag);
FREE(data);
}
close(fdDump);
return(id);
}
/*******************************************************************************
** Delete a linked list and clear info about it.
**
** Parameters:
** In int id identifier of linked list
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID
*/
#ifdef ANSI
int
lDel(int id)
#else
int
lDel(id)
int id;
#endif
{
ListPtr list;
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lDel", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
/* delete all nodes */
delNodes(list->first, list->n);
/* reset info as deleted linked list */
list->sd = list->cc = list->n = 0;
list->first = list->current = list->last = NULL;
return(lSUCCESS);
}
/*******************************************************************************
** Delete all linked list and all info about those lists.
**
** No parameters.
**
** Return on success:
** lSUCCESS
** Return on error:
** lNO_LIST
*/
#ifdef ANSI
int
lDelAll(void)
#else
int
lDelAll()
#endif
{
ListPtr list, nxt;
if (ld == NULL) {
lError("lDelAll", lNO_LIST, 0, 0, NULL);
return(lNO_LIST);
}
list = ld;
while (list != NULL) {
nxt = list->nxt;
if (list->sd != 0 && list->cc != 0)
lDel(list->id); /* delete when not already deleted */
list = nxt;
}
delListInfo(ld->nxt);
/* save info of initial list */
firstlist.id = 1;
firstlist.sd = firstlist.cc = firstlist.n = 0;
firstlist.first = firstlist.current = firstlist.last = NULL;
firstlist.nxt = NULL;
ld = &firstlist;
idMax = 2;
return(lSUCCESS);
}
/*******************************************************************************
** Insert a node in linked list.
**
** Parameters:
** In int id identifier of linked list
** In int where place where node must be inserted
** (lFIRST, lBEFORE, lAFTER, lLAST)
** In Byte *data data of node
** In int size size of data
** In int flag user information flag
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lWRONG_WHERE
*/
#ifdef ANSI
int
lInsNode(int id, int where, Byte *data, int size, int flag)
#else
int
lInsNode(id, where, data, size, flag)
int id, where, size, flag;
Byte *data;
#endif
{
ListPtr list;
NodePtr node, new;
static int set[] = { lFIRST, lBEFORE, lAFTER, lLAST };
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lInsNode", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (intInSet(where, set, 4) != 0) {
lError("lInsNode", lWRONG_WHERE, where, 0, NULL);
return(lWRONG_WHERE);
}
/* create new node */
MALLOC(new, ListNode);
CALLOC(new->data, Byte, size);
BYTE_COPY(data, new->data, size);
new->size = size;
new->flag = flag;
/* specific insert cases */
if (list->first == NULL)
where = lONE_NODE; /* first node in list */
else if (list->current == list->first && where == lBEFORE)
where = lFIRST; /* before first is like insert first */
else if (list->current == list->last && where == lAFTER)
where = lLAST; /* after last is like insert last */
switch (where) {
case lONE_NODE:
if (list->cc == lCHAIN)
new->prv = new->nxt = NULL;
else {
if (list->sd == lDOUBLY)
new->prv = new;
else
new->prv = NULL;
new->nxt = new;
}
list->first = list->last = new;
break;
case lFIRST:
new->prv = (list->first)->prv;
new->nxt = list->first;
if (list->cc == lCIRCULAR)
(list->last)->nxt = new;
else
(list->last)->nxt = NULL;
if (list->sd == lDOUBLY)
(list->first)->prv = new;
list->first = new;
break;
case lBEFORE:
new->prv = (list->current)->prv; /* == NULL if lSINGLY */
new->nxt = list->current;
if (list->sd == lDOUBLY) {
((list->current)->prv)->nxt = new;
(list->current)->prv = new;
} else {
node = list->first;
/* search for last before current */
while (node->nxt != list->current && node != list->last)
node = node->nxt;
node->nxt = new;
}
if (list->current == list->first)
list->first = new;
break;
case lAFTER:
if (list->sd == lDOUBLY)
new->prv = list->current;
else
new->prv = NULL;
new->nxt = (list->current)->nxt;
if (list->sd == lDOUBLY) {
((list->current)->nxt)->prv = new;
(list->current)->prv = new;
}
(list->current)->nxt = new;
if (list->current == list->last)
list->last = new;
break;
case lLAST:
node = list->last;
if (list->sd == lDOUBLY)
new->prv = node;
else
new->prv = NULL;
if (list->cc == lCIRCULAR)
new->nxt = list->first;
else
new->nxt = NULL;
if (list->sd == lDOUBLY && list->cc == lCIRCULAR)
(list->first)->prv = new;
node->nxt = new;
list->last = new;
break;
}
list->n++;
list->current = new;
return(lSUCCESS);
}
/*******************************************************************************
** Get info of node of linked list.
**
** Parameters:
** In int id identifier of linked list
** In int which which node must be inspected
** (lFIRST, lPREVIOUS, lCURRENT, lNEXT, lLAST)
** Out int *size size of data of node
** Out int *flag user information flag
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lNOT_DOUBLY
*/
#ifdef ANSI
int
lInfoNode(int id, int which, int *size, int *flag)
#else
int
lInfoNode(id, which, size, flag)
int id, which, *size, *flag;
#endif
{
ListPtr list;
int rtrn;
rtrn = setWhchNode(id, which, "lInfoNode");
if (rtrn != lSUCCESS) /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, */
return(rtrn); /* lEOL, lNOT_DOUBLY */
list = getAddress(id); /* already checked in setWhchNode */
/* copy information */
*size = (list->current)->size;
*flag = (list->current)->flag;
return(lSUCCESS);
}
/*******************************************************************************
** Get data of node.
**
** Parameters:
** In int id identifier of linked list
** In int which which node must be retrieved
** (lFIRST, lPREVIOUS, lCURRENT, lNEXT, lLAST)
** Out Byte *data data of node
** In int size size of data
**
** Return on success:
** lSUCCESS, lFIRST, lLAST
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lNOT_DOUBLY, lSIZE_NE
*/
#ifdef ANSI
int
lGetNode(int id, int which, Byte *data, int size)
#else
int
lGetNode(id, which, data, size)
int id, which, size;
Byte *data;
#endif
{
ListPtr list;
int rtrn;
rtrn = setWhchNode(id, which, "lInfoNode");
if (rtrn != lSUCCESS) /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, */
return(rtrn); /* lEOL, lNOT_DOUBLY */
list = getAddress(id); /* already checked in setWhchNode */
/* expected data and node must have same size */
if ((list->current)->size != size) {
lError("lGetNode", lSIZE_NE, size, (list->current)->size, NULL);
return(lSIZE_NE);
}
BYTE_COPY((list->current)->data, data, size);
if (list->current == list->first)
return(lFIRST);
else if (list->current == list->last)
return(lLAST);
return(lSUCCESS);
}
/*******************************************************************************
** Find node.
**
** Parameters:
** In int id identifier of linked list
** In int where from where must be searched
** In Func func function for checking the data on conditions
** In Byte *ptr data for comparison in function
** Out Byte *data data of node
** In int size size of data
**
** Return on success:
** lFOUND, lFIRST, lLAST, lNOT_FOUND
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHERE, lUNKNOWN_FUNC, lNOT_DOUBLY
*/
#ifdef ANSI
int
lFndNode(int id, int where, Func func, Byte *ptr, Byte *data, int size)
#else
int
lFndNode(id, where, func, ptr, data, size)
int id, where, size;
Func func;
Byte *ptr, *data;
#endif
{
NodePtr node;
ListPtr list;
int cmp = lNOT_FOUND;
static int set[] = { lFIRST, lNEXT, lPREVIOUS, lLAST };
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lFndNode", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError("lFndNode", lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
if (intInSet(where, set, 4) != 0) {
lError("lFndNode", lWRONG_WHERE, where, 0, NULL);
return(lWRONG_WHERE);
}
if (func == NULL) {
lError("lFndNode", lUNKNOWN_FUNC, (int) func, 0, NULL);
return(lUNKNOWN_FUNC);
}
/* set node for where searching must start */
switch (where) {
case lFIRST: node = list->first; break;
case lNEXT:
case lPREVIOUS: node = list->current; break;
case lLAST: node = list->last; break;
}
/* expected data and node must have same size */
if ((where == lFIRST || where == lLAST) && node->size == size) {
BYTE_COPY(node->data, data, size);
cmp = (*func)(ptr, data);
}
switch (where) {
case lFIRST: /* search forward */
case lNEXT:
while (cmp != lFOUND && node->nxt != NULL
&& node != list->last) {
node = node->nxt;
/* expected data and node must have same size */
if (node->size == size) {
BYTE_COPY(node->data, data, size);
cmp = (*func)(ptr, data);
}
}
if (cmp == lFOUND) {
list->current = node;
if (list->current == list->last)
return(lLAST);
}
break;
case lPREVIOUS: /* search backward */
case lLAST:
if (list->sd != lDOUBLY && cmp == lNOT_FOUND) {
lError("lFndNode", lNOT_DOUBLY, id, 0, NULL);
return(lNOT_DOUBLY);
}
while (cmp != lFOUND && node->prv != NULL
&& node->prv != list->first) {
node = node->prv;
/* expected data and node must have same size */
if (node->size == size) {
BYTE_COPY(node->data, data, size);
cmp = (*func)(ptr, data);
}
}
if (cmp == lFOUND) {
list->current = node;
if (list->current == list->first)
return(lFIRST);
}
break;
}
return(cmp); /* lFOUND, lNOT_FOUND */
}
/*******************************************************************************
** Get node by flag.
**
** Parameters:
** In int id identifier of linked list
** In int flag flag of node which must be retrieved
** Out Byte *data data of node
** In int size size of data
**
** Return on success:
** lFOUND, lFIRST, lLAST, lNOT_FOUND
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHERE, lSIZE_NE
*/
#ifdef ANSI
int
lFndFlagNode(int id, int where, int flag, Byte *data, int size)
#else
int
lFndFlagNode(id, where, flag, data, size)
int id, where, flag, size;
Byte *data;
#endif
{
NodePtr node;
ListPtr list;
static int set[] = { lFIRST, lNEXT, lPREVIOUS, lLAST };
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lFndFlagNode", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError("lFndFlagNode", lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
if (intInSet(where, set, 4) != 0) {
lError("lFndFlagNode", lWRONG_WHERE, where, 0, NULL);
return(lWRONG_WHERE);
}
/* set node for where searching must start */
switch (where) {
case lFIRST:
node = list->first;
break;
case lNEXT:
if ((list->current)->nxt == NULL)
return(lNOT_FOUND); /* end of list reached */
node = (list->current)->nxt;
break;
case lPREVIOUS:
if ((list->current)->prv == NULL)
return(lNOT_FOUND); /* begin of list reached */
node = (list->current)->prv;
break;
case lLAST:
node = list->last;
break;
}
/* search till begin/end of list */
switch (where) {
case lFIRST: /* search forward */
case lNEXT:
while (node->flag != flag && node != list->last)
node = node->nxt;
break;
case lPREVIOUS: /* search backward */
case lLAST:
if (list->sd != lDOUBLY) {
lError("lFndFlagNode", lNOT_DOUBLY, id, 0, NULL);
return(lNOT_DOUBLY);
}
while (node->flag != flag && node != list->first)
node = node->prv;
break;
}
list->current = node;
/* extra flag-check for last node of list */
if ((list->current)->flag != flag) {
lError("lFndFlagNode", lNOT_FOUND, id, 0, NULL);
return(lNOT_FOUND);
}
/* expected data and node must have same size */
if ((list->current)->size != size) {
lError("lFndFlagNode", lSIZE_NE, size, (list->current)->size,
NULL);
return(lSIZE_NE);
}
BYTE_COPY((list->current)->data, data, size);
if (list->current == list->first)
return(lFIRST);
else if (list->current == list->last)
return(lLAST);
return(lFOUND);
}
/*******************************************************************************
** Update curent node.
**
** Parameters:
** In int id identifier of linked list
** In Byte *data updated data of node
** In int size size of data
** In int flag updated user information flag
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST
*/
#ifdef ANSI
int
lUpdNode(int id, Byte *data, int size, int flag)
#else
int
lUpdNode(id, data, size, flag)
int id, size, flag;
Byte *data;
#endif
{
ListPtr list;
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lUpdNode", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError("lUpdNode", lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
/* if same size, replace node by updated node */
/* if not same size, insert updated node on current place */
if ((list->current)->size != size) {
FREE((list->current)->data);
CALLOC((list->current)->data, Byte, size);
(list->current)->size = size;
}
(list->current)->flag = flag;
BYTE_COPY(data, (list->current)->data, size);
return(lSUCCESS);
}
/*******************************************************************************
** Delete node.
**
** Parameters:
** In int id identifier of linked list
** In int which which node must be deleted
** (lFIRST, lCURRENT, lLAST)
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH
*/
#ifdef ANSI
int
lDelNode(int id, int which)
#else
int
lDelNode(id, which)
int id, which;
#endif
{
NodePtr node, prv, nxt;
ListPtr list;
static int set[] = { lFIRST, lCURRENT, lLAST };
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError("lDelNode", lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError("lDelNode", lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
if (intInSet(which, set, 3) != 0) {
lError("lDelNode", lWRONG_WHICH, which, 0, NULL);
return(lWRONG_WHICH);
}
/* specific delete cases */
if (list->n == 1)
which = lONE_NODE; /* one node in linked list */
else if (which == lCURRENT && list->first == list->current)
which = lFIRST; /* current is also first node */
else if (which == lCURRENT && list->last == list->current)
which = lLAST; /* current is also last node */
switch (which) {
case lONE_NODE:
node = list->first;
list->first = list->current = list->last = NULL;
break;
case lFIRST:
node = list->first;
nxt = node->nxt;
if (list->cc == lCIRCULAR) {
prv = list->last;
prv->nxt = nxt;
} else
prv = node->prv; /* == NULL if lSINGLY */
if (list->sd == lDOUBLY)
nxt->prv = prv;
list->first = list->current = nxt;
break;
case lCURRENT:
node = list->current;
nxt = node->nxt;
if (list->sd == lDOUBLY) {
prv = node->prv;
nxt->prv = prv;
} else {
prv = node = list->first;
while (node != list->current) {
prv = node;
node = node->nxt;
}
if (prv == node)
prv = list->last;
}
prv->nxt = nxt;
list->current = nxt;
break;
case lLAST:
node = list->last;
if (list->sd == lDOUBLY)
prv = node->prv;
else {
if (list->current != list->last)
prv = node = list->current;
else
prv = node = list->first;
while (node != list->last) {
prv = node;
node = node->nxt;
}
}
nxt = node->nxt;
if (list->sd == lDOUBLY && list->cc == lCIRCULAR)
nxt->prv = prv;
prv->nxt = nxt;
list->last = list->current = prv;
break;
}
FREE(node->data);
FREE(node);
list->n--;
return(lSUCCESS);
}
/*******************************************************************************
** Get information about node by index.
**
** Parameters:
** In int id identifier of linked list
** In int index index of node which must be inspected
** Out int *size size of data of node
** Out int *flag user information flag
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
*/
#ifdef ANSI
int
lInfoIndxNode(int id, int index, int *size, int *flag)
#else
int
lInfoIndxNode(id, index, size, flag)
int id, index, *size, *flag;
#endif
{
ListPtr list;
int rtrn;
rtrn = setIndxNode(id, index, "lInfoIndxNode");
if (rtrn != lSUCCESS)
return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
list = getAddress(id); /* already checked in setIndxNode */
/* copy information */
*size = (list->current)->size;
*flag = (list->current)->flag;
return(lSUCCESS);
}
/*******************************************************************************
** Get node by index.
**
** Parameters:
** In int id identifier of linked list
** In int index index of node which must be retrieved
** Out Byte *data data of node
** In int size size of data
**
** Return on success:
** lSUCCESS, lFIRST, lLAST
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX, lSIZE_NE
*/
#ifdef ANSI
int
lGetIndxNode(int id, int index, Byte *data, int size)
#else
int
lGetIndxNode(id, index, data, size)
int id, index, size;
Byte *data;
#endif
{
ListPtr list;
int rtrn;
rtrn = setIndxNode(id, index, "lGetIndxNode");
if (rtrn != lSUCCESS)
return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
list = getAddress(id); /* already checked in setIndxNode */
/* expected data and node must have same size */
if ((list->current)->size != size) {
lError("lGetIndxNode", lSIZE_NE, size, (list->current)->size,
NULL);
return(lSIZE_NE);
}
BYTE_COPY((list->current)->data, data, size);
if (list->current == list->first)
return(lFIRST);
else if (list->current == list->last)
return(lLAST);
return(lSUCCESS);
}
/*******************************************************************************
** Update node by index.
**
** Parameters:
** In int id identifier of linked list
** In int index index of node which must be updated
** In Byte *data updated data of node
** In int size size of data
** In int flag updated user information flag
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
*/
#ifdef ANSI
int
lUpdIndxNode(int id, int index, Byte *data, int size, int flag)
#else
int
lUpdIndxNode(id, index, data, size, flag)
int id, index, size, flag;
Byte *data;
#endif
{
ListPtr list;
int rtrn;
rtrn = setIndxNode(id, index, "lUpdIndxNode");
if (rtrn != lSUCCESS)
return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
list = getAddress(id); /* already checked in setIndxNode */
/* if same size, replace node by updated node */
/* if not same size, insert updated node on current place */
if ((list->current)->size != size) {
FREE((list->current)->data);
CALLOC((list->current)->data, Byte, size);
(list->current)->size = size;
}
(list->current)->flag = flag;
BYTE_COPY(data, (list->current)->data, size);
return(lSUCCESS);
}
/*******************************************************************************
** Delete node by index.
**
** Parameters:
** In int id identifier of linked list
** In int index index of node which must be deleted
**
** Return on success:
** lSUCCESS
** Return on error:
** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
*/
#ifdef ANSI
int
lDelIndxNode(int id, int index)
#else
int
lDelIndxNode(id, index)
int id, index;
#endif
{
int rtrn;
rtrn = setIndxNode(id, index, "lDelIndxNode");
if (rtrn != lSUCCESS)
return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
return(lDelNode(id, lCURRENT)); /* lSUCCESS */
}
/* ---------- static local functions ---------------------------------------- */
/* get address of list data */
#ifdef ANSI
static ListPtr
getAddress(int id)
#else
static ListPtr
getAddress(id)
int id;
#endif
{
ListPtr list;
list = ld;
while (list != NULL && list->id != id)
list = list->nxt;
if (list == NULL)
return(NULL); /* id not found */
if (list->sd == 0 && list->cc == 0) /* deleted linked list */
return(NULL); /* deleted linked list */
return(list);
}
/* delete nodes of a linked list */
#ifdef ANSI
static void
delNodes(NodePtr node, int n)
#else
static void
delNodes(node, n)
NodePtr node;
int n;
#endif
{
NodePtr nxt;
int i;
for (i=0; i<n; i++) {
nxt = node->nxt;
FREE(node->data);
FREE(node);
node = nxt;
}
}
/* delete info about linked list */
#ifdef ANSI
static void
delListInfo(ListPtr list)
#else
static void
delListInfo(list)
ListPtr list;
#endif
{
ListPtr nxt;
while (list != NULL) {
nxt = list->nxt;
FREE(list);
list = nxt;
}
}
/* print error message in lERROR_FILE */
#ifdef ANSI
static void
lError(char *str, int code, int int1, int int2, char *str1)
#else
static void
lError(str, code, int1, int2, str1)
char *str, *str1;
int code, int1, int2;
#endif
{
#ifndef MSDOS
char mess[60];
FILE *fpError, *fopen();
switch (code) {
case lWRONG_SD:
sprintf(mess, "Parameter 'sd' has wrong value : %d", int1);
break;
case lWRONG_CC:
sprintf(mess, "Parameter 'cc' has wrong value : %d", int1);
break;
case lWRONG_WHERE:
sprintf(mess, "Parameter 'where' has wrong value : %d", int1);
break;
case lWRONG_WHICH:
sprintf(mess, "Parameter 'which' has wrong value : %d", int1);
break;
case lUNKNOWN_ID:
sprintf(mess, "List id '%d' is unknown", int1);
break;
case lUNKNOWN_FUNC:
sprintf(mess, "Function '%d' is unknown", int1);
break;
case lNO_LIST:
sprintf(mess, "There are no lists defined");
break;
case lEMPTY_LIST:
#ifdef DEBUG
sprintf(mess, "List '%d' is empty", int1);
break;
#else
return;
#endif
case lEOL:
#ifdef DEBUG
sprintf(mess, "End of list '%d' reached", int1);
break;
#else
return;
#endif
case lNOT_FOUND:
#ifdef DEBUG
sprintf(mess, "Node not found in list '%d'", int1);
break;
#else
return;
#endif
case lNOT_DOUBLY:
sprintf(mess, "List '%d' is not doubly linked", int1);
break;
case lSIZE_NE:
sprintf(mess,
"Size of expected data '%d' and node '%d' not equal",
int1, int2);
break;
case lWRONG_INDEX:
sprintf(mess, "Index '%d' out of range [1:%d]", int1, int2);
break;
case lOPEN_ERROR:
sprintf(mess, "Can't open dump-file '%s'\n", str1);
break;
case lWRONG_ORDER:
sprintf(mess, "Parameter 'order' has wrong value : %d", int1);
break;
case lWRONG_THEORY:
sprintf(mess, "Parameter 'theory' has wrong value : %d", int1);
break;
}
fpError = fopen(lERROR_FILE, "a");
if (fpError == NULL) {
fprintf(stderr, "Can't open error-file '%s'\n", lERROR_FILE);
fprintf(stderr, "Error, '%s': %s\n", str, mess);
} else {
fprintf(fpError, "Error, '%s': %s\n", str, mess);
fclose(fpError);
}
#endif
}
#ifdef ANSI
static int
setWhchNode(int id, int which, char *fname)
#else
static int
setWhchNode(id, which, fname)
int id, which;
char *fname;
#endif
{
ListPtr list;
static int set[] = { lFIRST, lNEXT, lCURRENT, lPREVIOUS, lLAST };
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError(fname, lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError(fname, lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
if (intInSet(which, set, 5) != 0) {
lError(fname, lWRONG_WHICH, which, 0, NULL);
return(lWRONG_WHICH);
}
/* search for requested node */
switch (which) {
case lFIRST:
list->current = list->first;
break;
case lNEXT:
if ((list->current)->nxt == NULL) {
lError(fname, lEOL, id, 0, NULL);
return(lEOL);
}
list->current = (list->current)->nxt;
break;
case lCURRENT:
break;
case lPREVIOUS:
if (list->sd != lDOUBLY) {
lError(fname, lNOT_DOUBLY, id, 0, NULL);
return(lNOT_DOUBLY);
}
if ((list->current)->prv == NULL) {
lError(fname, lEOL, id, 0, NULL);
return(lEOL);
}
list->current = (list->current)->prv;
break;
case lLAST:
list->current = list->last;
break;
}
return(lSUCCESS);
}
#ifdef ANSI
static int
setIndxNode(int id, int index, char *fname)
#else
static int
setIndxNode(id, index, fname)
int id, index;
char *fname;
#endif
{
ListPtr list;
int i;
/* check parameters */
if ((list = getAddress(id)) == NULL) {
lError(fname, lUNKNOWN_ID, id, 0, NULL);
return(lUNKNOWN_ID);
}
if (list->n == 0) {
lError(fname, lEMPTY_LIST, id, 0, NULL);
return(lEMPTY_LIST);
}
if (index < 1 || list->n < index) {
lError(fname, lWRONG_INDEX, index, list->n, NULL);
return(lWRONG_INDEX);
}
if (index == 1)
list->current = list->first;
else if (index == list->n)
list->current = list->last;
else {
list->current = list->first;
for (i=1; i<index; i++)
list->current = (list->current)->nxt;
}
return(lSUCCESS);
}
/* local function for QUICK sort */
#ifdef ANSI
static int
partition(NodePtr *array, int order, Func func, int lb, int ub, int *pj)
#else
static int
partition(array, order, func, lb, ub, pj)
NodePtr *array;
int order, lb, ub, *pj;
Func func;
#endif
{
int down, up, cmp;
NodePtr temp, a;
a = array[lb];
up = ub;
down = lb;
while (down < up) {
cmp = (*func)(array[down]->data, a->data);
while (down < ub
&& ((order == lASCENDING && (cmp == l1LT2 || cmp == lSAME))
|| (order == lDESCENDING && (cmp == l2LT1 || cmp == lSAME)))) {
down++;
cmp = (*func)(array[down]->data, a->data);
}
cmp = (*func)(array[up]->data, a->data);
while ((order == lASCENDING && cmp == l2LT1)
|| (order == lDESCENDING && cmp == l1LT2)) {
up--;
cmp = (*func)(array[up]->data, a->data);
}
if (down < up) { /* interchange */
temp = array[down];
array[down] = array[up];
array[up] = temp;
}
}
array[lb] = array[up];
array[up] = a;
*pj = up;
}
/* local function for QUICK sort */
#ifdef ANSI
static int
stack_empty(int id)
#else
static int
stack_empty(id)
int id;
#endif
{
int sd, cc, n;
/* check to see if linked list exists */
if (lInfo(id, &sd, &cc, &n) == lUNKNOWN_ID)
return(1); /* linked list is non-existant */
if (n == 0)
return(1);
return(0);
}
/* ---------- static local functions (~anita/Tools/Clib) -------------------- */
/* check if integer belongs to set of integers */
static int
intInSet(intgr, set, set_n)
int intgr, *set, set_n;
{
int i = 0;
while (set[i] != intgr && i < set_n)
i++;
/* 0 = yes, 1 = no */
return((i == set_n) ? 1 : 0);
}